package com.polaris.live.popup

import android.content.Context
import android.graphics.Paint
import android.graphics.Rect
import android.view.View
import androidx.recyclerview.widget.GridLayoutManager
import com.blankj.utilcode.util.ColorUtils
import com.blankj.utilcode.util.StringUtils
import com.lxj.xpopup.core.BottomPopupView
import com.polaris.live.R
import com.polaris.live.adapter.DaysAdapter
import com.polaris.live.common.cacha.UserManager
import com.polaris.live.common.constant.AppConst
import com.polaris.live.common.constant.CommonConst
import com.polaris.live.common.ext.autoDp
import com.polaris.live.common.ext.formatNumberWithK
import com.polaris.live.common.ext.setOnSingleClickListener
import com.polaris.live.common.mvvm.viewmodel.BaseViewModel
import com.polaris.live.common.network.AppException
import com.polaris.live.common.network.requestLoading
import com.polaris.live.common.util.NavigationBarUtils
import com.polaris.live.common.util.ToastGravity
import com.polaris.live.common.util.ViewUtils
import com.polaris.live.databinding.PopupCommodityBinding
import com.polaris.live.dialog.OpenVipDialog
import com.polaris.live.dialog.PurchaseConfirmationDialog
import com.polaris.live.dialog_fragment.GiveFragmentDialog
import com.polaris.live.im.manager.ImNoticeManager
import com.polaris.live.net.payerService
import com.polaris.live.net.userService
import com.polaris.live.resp.back_resp.DiscountCornerMark
import com.polaris.live.resp.back_resp.PayerShopResp
import com.polaris.live.resp.bean.DaysBean
import com.polaris.live.resp.bean.ShopConfirmationBean
import com.polaris.live.resp.go_resp.BuyBackgroundRequest
import com.polaris.live.resp.go_resp.ShopBuyRequest
import com.polaris.live.resp.go_resp.UseDressUpBean
import com.polaris.live.translation.R.string
import com.polaris.live.utils.AppConfigUtils
import com.polaris.live.utils.CommonUtils
import com.polaris.live.utils.NinePatchDrawableUtil
import com.polaris.live.utils.fragment.FragmentUtils

/**
 * 商品结算pop
 *
 * @author Created by 天晴 on 2024/7/17 16:24
 * @since 1.0.0
 **/
class CommodityPopup(
    context: Context,
    val mViewModel: BaseViewModel,
    private var mPayerShopResp: PayerShopResp,
    private val mIsNeedBottom: Boolean,
    private val mIsHaveGiveaway: Boolean = true,
    private val onShow: ((show: Boolean) -> Unit)? = null,
    private val mBuySuccess: ((type: Long) -> Unit)? = null,
    private val mToLook: ((type: Long) -> Unit)? = null,
) : BottomPopupView(context) {

    private lateinit var mBinding: PopupCommodityBinding

    override fun getImplLayoutId(): Int {
        return R.layout.popup_commodity
    }

    private val mDaysAdapter by lazy { DaysAdapter() }

    private var isUp = true

    private val daysList = mutableListOf<DaysBean>()

    private var mPayType = TYPE_DIAMOND //  * 支付类型0: 金币1: 金豆4: 游戏币

    private val mDecorationNames by lazy {
        AppConfigUtils.getDecorationNames()
    }

    override fun onCreate() {
        mBinding = PopupCommodityBinding.bind(popupImplView)
        val account = UserManager.getUser().account
        mBinding.apply {
            nameTv.setText(mPayerShopResp.shopName, true)
            gameCoinTv.text = account?.userGameCoins.formatNumberWithK()
            diamondTv.text = account?.userCoins.formatNumberWithK()
            beansTv.text = account?.gainCoins.formatNumberWithK()
            if (CommonUtils.isMiddleEast(UserManager.getUser().flag?.region)) {
                beansCoinCl.visibility = View.GONE
                beansLl.visibility = View.GONE
            } else {
                beansTv.text = account?.gainCoins.formatNumberWithK()
            }
        }
        if (!mIsHaveGiveaway) {
            mBinding.giveTv.visibility = View.GONE
        }
        initData()
        setDefCoins()
        if (daysList.isNotEmpty()) {
            setPayTypeStatus(daysList[0])
            setPayType()
            mDaysAdapter.setSelect(0)
        }
        setType()
        initObserve()
        initListener()
        initRecyclerView()
        if (mIsNeedBottom) {
            ViewUtils.setMargin(mBinding.bottomView, 0, 0, 0, NavigationBarUtils.getNavigationBarHeight(context))
        }
    }

    fun upData(payerShopResp: PayerShopResp) {
        if (!::mBinding.isInitialized) return
        mPayerShopResp = payerShopResp
        daysList.clear()
        mPayType = TYPE_DIAMOND
        isUp = true
        mDaysAdapter.data.clear()
        mDaysAdapter.notifyDataSetChanged()

        mBinding.nameTv.setText(mPayerShopResp.shopName, true)
        initData()
        setDefCoins()
        if (daysList.isNotEmpty()) {
            setPayTypeStatus(daysList[0])
            setPayType()
            mDaysAdapter.setSelect(0)
        }
        setType()
        mDaysAdapter.setList(daysList)
    }

    private fun initData() {
        mPayerShopResp.coins?.forEach {
            daysList.add(
                DaysBean(
                    it.key.toInt(),
                    it.toPair(),
                    mPayerShopResp.discountCoins,
                    mPayerShopResp.discountCoinCornerMarks,
                    null,
                    null,
                    null,
                    null,
                    null,
                    null
                )
            )
        }
        mPayerShopResp.gameCoins?.forEach {
            val bean = daysList.find { daysBean -> daysBean.days == it.key.toInt() }
            if (bean != null) {
                bean.gameCoins = it.toPair()
                bean.discountGameCoins = mPayerShopResp.discountGameCoins
                bean.discountGameCoinCornerMarks = mPayerShopResp.discountGameCoinCornerMarks
            } else {
                daysList.add(
                    DaysBean(
                        it.key.toInt(),
                        null,
                        null,
                        null,
                        it.toPair(),
                        mPayerShopResp.discountGameCoinCornerMarks,
                        mPayerShopResp.discountGameCoins,
                        null,
                        null,
                        null
                    )
                )
            }
        }
        mPayerShopResp.gainCoins?.forEach {
            val bean = daysList.find { daysBean -> daysBean.days == it.key.toInt() }
            if (bean != null) {
                bean.gainCoins = it.toPair()
                bean.discountGainCoins = mPayerShopResp.discountGainCoins
                bean.discountGainCoinCornerMarks = mPayerShopResp.discountGainCoinCornerMarks
            } else {
                daysList.add(
                    DaysBean(
                        it.key.toInt(),
                        null,
                        null,
                        null,
                        null,
                        null,
                        null,
                        it.toPair(),
                        mPayerShopResp.discountGainCoinCornerMarks,
                        mPayerShopResp.discountGainCoins
                    )
                )
            }
        }
        daysList.sortWith { a1, a2 ->
            when {
                a1.days == -1 && a2.days != -1 -> 1
                a1.days != -1 && a2.days == -1 -> -1
                else -> a2.days.compareTo(a2.days)
            }
        }
    }

    private fun initRecyclerView() {
        mBinding.daysRecycler.apply {
            adapter = mDaysAdapter
            layoutManager = GridLayoutManager(context, 3)
        }
        mDaysAdapter.setList(daysList)
    }

    private fun initListener() {
        mBinding.contextLl.setOnSingleClickListener {
        }
        mBinding.diamondLl.setOnSingleClickListener {
            GlobalPopupManager.showRechargePopup(
                context,
                mViewModel,
                isNeedBottom = true
            )
        }
        mBinding.gameCoinLl.setOnSingleClickListener {
            GlobalPopupManager.showExchangeGamePopup(context, mViewModel)
        }
        mBinding.buyTv.setOnSingleClickListener {
            GlobalPopupManager.showCompletePopup(context, isOk = {
                vipShoppingcheck {
                    showSureDialog()
                }
            })
        }
        mBinding.diamondCl.setOnSingleClickListener {
            mPayType = TYPE_DIAMOND
            setPayType()
            mDaysAdapter.getSelectData()?.let {
                setCoins(it)
            }
        }
        mBinding.gameCoinCl.setOnSingleClickListener {
            mPayType = TYPE_GAME_COIN
            setPayType()
            mDaysAdapter.getSelectData()?.let {
                setCoins(it)
            }
        }
        mBinding.beansCoinCl.setOnSingleClickListener {
            mPayType = TYPE_GAIN_BEANS
            setPayType()
            mDaysAdapter.getSelectData()?.let {
                setCoins(it)
            }
        }
        mBinding.giveTv.setOnSingleClickListener {
            GlobalPopupManager.showCompletePopup(context, isOk = {
                vipShoppingcheck {
                    val fragmentManager = FragmentUtils.getFragmentManager(context)
                        ?: return@vipShoppingcheck
                    GiveFragmentDialog().apply {
                        setUserCallback {
                            showSureDialog(it.userId, it.nickname)
                        }
                    }.show(fragmentManager, "GiveFragmentDialog")
                }
            })
        }
        mBinding.coinsLl.setOnSingleClickListener {
            isUp = !isUp
            mBinding.upDownImg.setImageResource(if (isUp) R.drawable.commodity_up else R.drawable.commodity_down)
            if (isUp) {
                mBinding.skuLl.visibility = GONE
            } else {
                mBinding.skuLl.visibility = VISIBLE
            }
        }
        mDaysAdapter.setOnItemClickListener { adapter, view, position ->
            val bean = mDaysAdapter.getItem(position)
            mDaysAdapter.setSelect(position)

            setPayTypeStatus(bean)
            when (mPayType) {
                TYPE_DIAMOND -> {
                    if (bean.diamond == null) {
                        if (bean.gameCoins != null) {
                            mPayType = TYPE_GAME_COIN
                        } else if (bean.gainCoins != null) {
                            mPayType = TYPE_GAIN_BEANS
                        }
                    }
                }

                TYPE_GAME_COIN -> {
                    if (bean.gameCoins == null) {
                        if (bean.diamond != null) {
                            mPayType = TYPE_DIAMOND
                        } else if (bean.gainCoins != null) {
                            mPayType = TYPE_GAIN_BEANS
                        }
                    }
                }

                TYPE_GAIN_BEANS -> {
                    if (bean.gainCoins == null) {
                        if (bean.diamond != null) {
                            mPayType = TYPE_DIAMOND
                        } else if (bean.gameCoins != null) {
                            mPayType = TYPE_GAME_COIN
                        }
                    }
                }
            }
            setCoins(bean)
        }

    }

    private fun initObserve() {
        //余额变动
        ImNoticeManager.observeAccountChange(this) {
            mBinding.diamondTv.text = UserManager.getUser().account?.userCoins.formatNumberWithK()
            mBinding.beansTv.text = UserManager.getUser().account?.gainCoins.formatNumberWithK()
        }
        //资产修改
        ImNoticeManager.observeGameAccountChange(this) {
            mBinding.gameCoinTv.text =
                UserManager.getUser().account?.userGameCoins.formatNumberWithK()
        }

    }

    /*
    设置装饰类型
     */
    private fun setType() {
        when (mPayerShopResp.objectType) {
            CommonConst.DressUp.AVATAR_FRAME -> {
                mBinding.typeTv.text = mDecorationNames?.get("${CommonConst.DressUp.AVATAR_FRAME}")
                    ?: StringUtils.getString(string.shopping_avatar)
            }

            CommonConst.DressUp.CHAT_BUBBLE -> {
                mBinding.typeTv.text = mDecorationNames?.get("${CommonConst.DressUp.CHAT_BUBBLE}")
                    ?: StringUtils.getString(string.shopping_bubble)
            }

            CommonConst.DressUp.LIVE_BROADCAST_ENTRY -> {
                mBinding.typeTv.text = mDecorationNames?.get("${CommonConst.DressUp.LIVE_BROADCAST_ENTRY}")
                    ?: StringUtils.getString(string.shopping_car)
            }

            CommonConst.DressUp.USER_PROFILE -> {
                mBinding.typeTv.text = mDecorationNames?.get("${CommonConst.DressUp.USER_PROFILE}")
                    ?: StringUtils.getString(string.shopping_info_card)
            }

            CommonConst.DressUp.HOMEPAGE_BACKGROUND -> {
                mBinding.typeTv.text = mDecorationNames?.get("${CommonConst.DressUp.HOMEPAGE_BACKGROUND}")
                    ?: StringUtils.getString(string.shopping_floating)
            }

            CommonConst.DressUp.LIVE_EFFECT -> {
                mBinding.typeTv.text = mDecorationNames?.get("${CommonConst.DressUp.LIVE_EFFECT}")
                    ?: StringUtils.getString(string.shopping_entrance)
            }

            CommonConst.DressUp.PARTY_BACKGROUND -> {
                mBinding.typeTv.text = mDecorationNames?.get("${CommonConst.DressUp.PARTY_BACKGROUND}")
                    ?: StringUtils.getString(string.shopping_background)
            }
        }
    }

    private fun setDefCoins() {
        if (daysList.isNotEmpty()) {
            val bean = daysList[0]
            val diamond = bean.diamond
            if (diamond != null) {
                mPayType = TYPE_DIAMOND
                mBinding.coinsImg.setImageResource(R.drawable.layer_diamond_icon)
                val discountCon = bean.discountCoins?.get(bean.days.toString())
                setCoinsTv(TYPE_DIAMOND, diamond, discountCon)
                val discountConMarks = bean.discountCoinCornerMarks?.get(bean.days.toString())
                setMarks(discountConMarks)
                return
            }
            val gameCoins = bean.gameCoins
            if (gameCoins != null) {
                mPayType = TYPE_GAME_COIN
                mBinding.coinsImg.setImageResource(R.drawable.layer_game_coin)
                val discountGameCon = bean.discountGameCoins?.get(bean.days.toString())
                setCoinsTv(TYPE_GAME_COIN, gameCoins, discountGameCon)

                val discountConMarks = bean.discountGameCoinCornerMarks?.get(bean.days.toString())
                setMarks(discountConMarks)

            }
            val gain = bean.gainCoins
            if (gain != null) {
                mPayType = TYPE_GAIN_BEANS
                mBinding.coinsImg.setImageResource(R.drawable.anchor_ic_beans)
                val discountGainCoins = bean.discountGainCoins?.get(bean.days.toString())
                setCoinsTv(TYPE_GAME_COIN, gain, discountGainCoins)
                val discountConMarks = bean.discountGainCoinCornerMarks?.get(bean.days.toString())
                setMarks(discountConMarks)
            }
        }
    }

    private fun setCoinsTv(type: Int, coins: Pair<String, Long>, discountGameCon: Long?) {
        if (discountGameCon != null) {
            mBinding.coinsTv.text = "$discountGameCon"
            mBinding.coinsTv2.text = "${coins.second}"
        } else {
            mBinding.coinsTv.text = "${coins.second}"
            mBinding.coinsTv2.text = ""
        }
        mBinding.coinsTv.setTextColor(
            if (type == TYPE_DIAMOND) ColorUtils.getColor(R.color.color_ff8c00) else ColorUtils.getColor(
                R.color.color_10bbff
            )
        )
        mBinding.coinsTv2.paintFlags =
            mBinding.coinsTv2.paintFlags or Paint.STRIKE_THRU_TEXT_FLAG
        val str3 = if (coins.first.toInt() == -1) {
            "/${StringUtils.getString(string.permanent)}"
        } else {
            "/${coins.first}${StringUtils.getString(string.one_days)}"
        }
        mBinding.coinsTv3.text = str3

    }

    private fun setMarks(discountConMarks: DiscountCornerMark?) {
        if (discountConMarks == null) {
            mBinding.discountTv.visibility = View.INVISIBLE
        } else {
            mBinding.discountTv.visibility = View.VISIBLE
            mBinding.discountTv.text = discountConMarks.cornerMarkText
            NinePatchDrawableUtil.getNinePatchDrawable(discountConMarks.cornerMarkURL,
                Rect(7.autoDp, 0.autoDp, 7.autoDp, 0.autoDp), { nine ->
                    mBinding.discountTv.background = nine
                }) {

            }
        }

    }

    private fun setCoins(bean: DaysBean) {
        when (mPayType) {
            TYPE_DIAMOND -> {
                bean.diamond?.let {
                    mBinding.coinsImg.setImageResource(R.drawable.layer_diamond_icon)
                    val discountCon = bean.discountCoins?.get(bean.days.toString())
                    setCoinsTv(TYPE_DIAMOND, it, discountCon)
                    val discountConMarks = bean.discountCoinCornerMarks?.get(bean.days.toString())
                    setMarks(discountConMarks)
                }
            }

            TYPE_GAME_COIN -> {
                bean.gameCoins?.let {
                    mBinding.coinsImg.setImageResource(R.drawable.layer_game_coin)
                    val discountGameCon = bean.discountGameCoins?.get(bean.days.toString())
                    setCoinsTv(TYPE_GAME_COIN, it, discountGameCon)

                    val discountConMarks = bean.discountGameCoinCornerMarks?.get(bean.days.toString())
                    setMarks(discountConMarks)
                }
            }

            TYPE_GAIN_BEANS -> {
                bean.gainCoins?.let {
                    mBinding.coinsImg.setImageResource(R.drawable.anchor_ic_beans)
                    val discountGainCoins = bean.discountGainCoins?.get(bean.days.toString())
                    setCoinsTv(TYPE_GAIN_BEANS, it, discountGainCoins)

                    val discountConMarks = bean.discountGainCoinCornerMarks?.get(bean.days.toString())
                    setMarks(discountConMarks)
                }
            }
        }

    }

    /**
     * 这个价位是否可以支付的状态
     */
    private fun setPayTypeStatus(bean: DaysBean) {
        if (bean.diamond == null) {
            mBinding.diamondCl.alpha = 0.5f
            mBinding.diamondCl.isClickable = false
        } else {
            mBinding.diamondCl.alpha = 1f
            mBinding.diamondCl.isClickable = true
        }
        if (bean.gameCoins == null) {
            mBinding.gameCoinCl.alpha = 0.5f
            mBinding.gameCoinCl.isClickable = false
        } else {
            mBinding.gameCoinCl.alpha = 1f
            mBinding.gameCoinCl.isClickable = true
        }
        if (bean.gainCoins == null) {
            mBinding.beansCoinCl.alpha = 0.5f
            mBinding.beansCoinCl.isClickable = false
        } else {
            mBinding.beansCoinCl.alpha = 1f
            mBinding.beansCoinCl.isClickable = true
        }
    }

    private fun setPayType() {
        when (mPayType) {
            TYPE_DIAMOND -> {
                mBinding.diamondIndex.visibility = VISIBLE
                mBinding.gameCoinIndex.visibility = GONE
                mBinding.beansCoinIndex.visibility = GONE
            }

            TYPE_GAME_COIN -> {
                mBinding.diamondIndex.visibility = GONE
                mBinding.gameCoinIndex.visibility = VISIBLE
                mBinding.beansCoinIndex.visibility = GONE
            }

            TYPE_GAIN_BEANS -> {
                mBinding.diamondIndex.visibility = GONE
                mBinding.gameCoinIndex.visibility = GONE
                mBinding.beansCoinIndex.visibility = VISIBLE
            }
        }
        mDaysAdapter.setPayType(mPayType)
    }

    //购买背景槽位
    private fun buyBackgroundRequest() {
        val coinType = mPayType.toLong()
        val data = mDaysAdapter.getSelectData() ?: return
        val day = data.days.toLong()

        mViewModel.requestLoading({
            userService.buyPartyBackground(BuyBackgroundRequest(coinType, day, mPayerShopResp.shopId))
        }, {
            mBuySuccess?.invoke(mPayerShopResp.objectType)
            ToastGravity.showGravity(StringUtils.getString(string.buy_success_go_upload_diy_background))
            dismiss()
        }, {
            errorEvent(it)
        })
    }

    //购买普通商品
    private fun buyCommodityRequest(otherUserId: Long? = null, discountBackpackId: Long?, voucherBackpackId: Long?) {
        val coinType: Long = mPayType.toLong()
        val data = mDaysAdapter.getSelectData() ?: return
        val day = data.days.toLong()

        mViewModel.requestLoading(
            {
                payerService.shopBuy(
                    ShopBuyRequest(
                        coinType,
                        day,
                        otherUserId,
                        mPayerShopResp.shopId,
                        discountBackpackId,
                        voucherBackpackId
                    )
                )
            }, {
                if (otherUserId == null) {
                    mBuySuccess?.invoke(mPayerShopResp.objectType)
                }
                BuySuccessPopup.show(context, mPayerShopResp, data.days, otherUserId, {
                    onShow?.invoke(it)
                }, {
                    dismiss()
                    mToLook?.invoke(mPayerShopResp.objectType)
                }, {
                    useDressUp(it.objectId, AppConst.YES)
                })

            }, {
                errorEvent(it)
            }
        )
    }

    private fun errorEvent(appException: AppException) {
        when (appException.errCode) {
            CommonConst.ErrorCode.SENDGIFT -> {
                GlobalPopupManager.showRechargePopup(
                    context,
                    mViewModel,
                    isNeedBottom = true
                )
            }

            CommonConst.ErrorCode.GAME_BEANS -> {
                GlobalPopupManager.showExchangeGamePopup(context, mViewModel)
            }

            CommonConst.ErrorCode.VIP_LEVEL_INSUFFICIENT -> {
                mPayerShopResp.vipLevel?.let {
                    OpenVipDialog.show(
                        context,
                        StringUtils.getString(string.this_vip_buy_commodity, "VIP${it}"),
                        it
                    )
                }

            }
        }
        ToastGravity.showGravity(appException.errorMsg)
    }

    /**
     * 二次确认弹窗  如果传递了userId 和 nickName 就表示要购买   如果没穿就表示赠送
     * ps: 要么都传 要么都不传， 不可以只传一个
     */
    private fun showSureDialog(userId: Long? = null, nickName: String? = null) {
        val data = mDaysAdapter.getSelectData() ?: return
        val money = when (mPayType) {
            TYPE_DIAMOND -> data.diamond?.let { data.discountCoins?.get(data.days.toString()) }
            TYPE_GAME_COIN -> data.gameCoins?.let { data.discountGameCoins?.get(data.days.toString()) }
            TYPE_GAIN_BEANS -> data.gainCoins?.let { data.discountGainCoins?.get(data.days.toString()) }
            else -> null
        }
        val originalPrice = when (mPayType) {
            TYPE_DIAMOND -> data.diamond?.second
            TYPE_GAME_COIN -> data.gameCoins?.second
            TYPE_GAIN_BEANS -> data.gainCoins?.second
            else -> null
        } ?: return

        if (mPayerShopResp.objectType == CommonConst.DressUp.DIY_BACKGROUND) {
            buyBackgroundRequest()
        } else {
            PurchaseConfirmationDialog.show(
                context, mViewModel, ShopConfirmationBean(
                    mPayerShopResp.shopName,
                    money ?: originalPrice,
                    originalPrice,
                    data.days.toLong(),
                    mPayerShopResp.displayUrl,
                    mPayType,
                    nickName
                )
            ) { discountBackpackId, voucherBackpackId ->
                buyCommodityRequest(userId, discountBackpackId, voucherBackpackId)
            }
        }
    }

    private fun vipShoppingcheck(checkState: () -> Unit) {
        val shopVipLevel = mPayerShopResp.vipLevel
        val userVipLevel = UserManager.getUser().profile?.vipLevel ?: -1
        if (shopVipLevel != null && userVipLevel < shopVipLevel) {
            OpenVipDialog.show(
                context,
                StringUtils.getString(string.this_vip_buy_commodity, "VIP${shopVipLevel}"),
                shopVipLevel
            )
        } else {
            checkState.invoke()
        }
    }

    /**
     * 使用装饰
     */
    private fun useDressUp(
        backpackId: Long,
        useStatus: Int,
    ) {
        val useDressUp = UseDressUpBean(backpackId, useStatus)
        mViewModel.requestLoading({ userService.useDressUp(useDressUp) }, {
            mBuySuccess?.invoke(mPayerShopResp.objectType)
            ToastGravity.showGravity(StringUtils.getString(string.successfully_worn))
        }, {
            ToastGravity.showGravity(it.errorMsg)
        }, waitTime = 0)
    }

    companion object {

        //支付类型
        const val TYPE_DIAMOND = 0
        const val TYPE_GAME_COIN = 4
        const val TYPE_GAIN_BEANS = 1

    }
}